package com.datareport.compute;

import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 数据脱敏处理器
 * 对敏感字段进行脱敏处理，满足业务需求5.3节安全要求
 */
@Slf4j
public class DataMaskingProcessor {

    private static final Map<String, MaskingStrategy> MASKING_RULES = new HashMap<>();

    static {
        // 银行卡号脱敏：保留后4位，如****1234
        MASKING_RULES.put("card_no", new MaskingStrategy(
                value -> "****" + (value != null && value.length() >= 4 ? 
                    value.substring(value.length() - 4) : "****"),
                "银行卡号"
        ));
        
        // 手机号脱敏：保留前3位和后4位，如138****5678
        MASKING_RULES.put("phone", new MaskingStrategy(
                value -> {
                    if (value != null && value.length() == 11) {
                        return value.substring(0, 3) + "****" + value.substring(7);
                    }
                    return "****";
                },
                "手机号"
        ));
        
        // 身份证号脱敏：保留前6位和后4位
        MASKING_RULES.put("id_card", new MaskingStrategy(
                value -> {
                    if (value != null && value.length() >= 10) {
                        return value.substring(0, 6) + "****" + value.substring(value.length() - 4);
                    }
                    return "****";
                },
                "身份证号"
        ));

        // 姓名脱敏：保留姓氏，如张**
        MASKING_RULES.put("name", new MaskingStrategy(
                value -> {
                    if (value != null && value.length() > 1) {
                        return value.charAt(0) + "*".repeat(value.length() - 1);
                    }
                    return value != null ? "*" : null;
                },
                "姓名"
        ));

        // 邮箱脱敏：保留前3位和域名，如abc***@example.com
        MASKING_RULES.put("email", new MaskingStrategy(
                value -> {
                    if (value != null && value.contains("@")) {
                        String[] parts = value.split("@");
                        if (parts[0].length() > 3) {
                            return parts[0].substring(0, 3) + "***@" + parts[1];
                        } else {
                            return "***@" + parts[1];
                        }
                    }
                    return "****@****";
                },
                "邮箱"
        ));

        // 地址脱敏：保留前6位，如北京市海淀区***
        MASKING_RULES.put("address", new MaskingStrategy(
                value -> {
                    if (value != null && value.length() > 6) {
                        return value.substring(0, 6) + "***";
                    }
                    return value != null ? value + "***" : null;
                },
                "地址"
        ));
    }

    /**
     * 对数据进行脱敏处理
     * @param data 原始数据
     * @return 脱敏后的数据
     */
    public static Map<String, Object> maskData(Map<String, Object> data) {
        if (data == null || data.isEmpty()) {
            return data;
        }

        Map<String, Object> maskedData = new HashMap<>(data);
        
        for (Map.Entry<String, MaskingStrategy> entry : MASKING_RULES.entrySet()) {
            String field = entry.getKey();
            MaskingStrategy strategy = entry.getValue();
            
            if (data.containsKey(field)) {
                Object originalValue = data.get(field);
                if (originalValue != null) {
                    try {
                        String maskedValue = strategy.mask(originalValue.toString());
                        maskedData.put(field, maskedValue);
                        
                        if (log.isDebugEnabled()) {
                            log.debug("字段[{}]脱敏完成: {} -> {}", 
                                    strategy.getFieldName(), originalValue, maskedValue);
                        }
                    } catch (Exception e) {
                        log.warn("字段[{}]脱敏失败，保持原值: {}", field, originalValue, e);
                        maskedData.put(field, originalValue);
                    }
                }
            }
        }
        
        return maskedData;
    }

    /**
     * 对单个字段进行脱敏处理
     * @param fieldName 字段名
     * @param value 字段值
     * @return 脱敏后的值
     */
    public static String maskField(String fieldName, String value) {
        if (fieldName == null || value == null) {
            return value;
        }

        MaskingStrategy strategy = MASKING_RULES.get(fieldName);
        if (strategy != null) {
            try {
                return strategy.mask(value);
            } catch (Exception e) {
                log.warn("字段[{}]脱敏失败，返回原值: {}", fieldName, value, e);
                return value;
            }
        }
        
        return value;
    }

    /**
     * 判断字段是否需要脱敏
     * @param fieldName 字段名
     * @return 是否需要脱敏
     */
    public static boolean needMasking(String fieldName) {
        return MASKING_RULES.containsKey(fieldName);
    }

    /**
     * 添加自定义脱敏规则
     * @param fieldName 字段名
     * @param maskingFunction 脱敏函数
     * @param fieldDescription 字段描述
     */
    public static void addMaskingRule(String fieldName, Function<String, String> maskingFunction, String fieldDescription) {
        MASKING_RULES.put(fieldName, new MaskingStrategy(maskingFunction, fieldDescription));
        log.info("添加自定义脱敏规则: {} - {}", fieldName, fieldDescription);
    }

    /**
     * 获取所有支持的脱敏字段
     * @return 脱敏字段列表
     */
    public static Map<String, String> getSupportedFields() {
        Map<String, String> supportedFields = new HashMap<>();
        for (Map.Entry<String, MaskingStrategy> entry : MASKING_RULES.entrySet()) {
            supportedFields.put(entry.getKey(), entry.getValue().getFieldName());
        }
        return supportedFields;
    }

    /**
     * 脱敏策略类
     */
    public static class MaskingStrategy {
        private final Function<String, String> maskingFunction;
        private final String fieldName;

        public MaskingStrategy(Function<String, String> maskingFunction, String fieldName) {
            this.maskingFunction = maskingFunction;
            this.fieldName = fieldName;
        }

        public String mask(String value) {
            if (value == null) {
                return null;
            }
            return maskingFunction.apply(value);
        }

        public String getFieldName() {
            return fieldName;
        }
    }
}